home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / tools / gcc / gcc270_src.lha / gcc-2.7.0-amiga / config / h8300 / lib1funcs.asm < prev    next >
Encoding:
Assembly Source File  |  1995-06-15  |  11.7 KB  |  704 lines

  1. ;; libgcc1 routines for the Hitachi h8/300 cpu.
  2. ;; Contributed by Steve Chamberlain.
  3. ;; sac@cygnus.com
  4.  
  5. /* Copyright (C) 1994 Free Software Foundation, Inc.
  6.  
  7. This file is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. In addition to the permissions in the GNU General Public License, the
  13. Free Software Foundation gives you unlimited permission to link the
  14. compiled version of this file with other programs, and to distribute
  15. those programs without any restriction coming from the use of this
  16. file.  (The General Public License restrictions do apply in other
  17. respects; for example, they cover modification of the file, and
  18. distribution when not linked into another program.)
  19.  
  20. This file is distributed in the hope that it will be useful, but
  21. WITHOUT ANY WARRANTY; without even the implied warranty of
  22. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  23. General Public License for more details.
  24.  
  25. You should have received a copy of the GNU General Public License
  26. along with this program; see the file COPYING.  If not, write to
  27. the Free Software Foundation, 59 Temple Place - Suite 330,
  28. Boston, MA 02111-1307, USA.  */
  29.  
  30. /* As a special exception, if you link this library with other files,
  31.    some of which are compiled with GCC, to produce an executable,
  32.    this library does not by itself cause the resulting executable
  33.    to be covered by the GNU General Public License.
  34.    This exception does not however invalidate any other reasons why
  35.    the executable file might be covered by the GNU General Public License.  */
  36.  
  37. /* Assembler register definitions.  */
  38.  
  39. #define A0 r0
  40. #define A0L r0l
  41. #define A0H r0h
  42.  
  43. #define A1 r1
  44. #define A1L r1l
  45. #define A1H r1h
  46.  
  47. #define A2 r2
  48. #define A2L r2l
  49. #define A2H r2h
  50.  
  51. #define A3 r3
  52. #define A3L r3l
  53. #define A3H r3h
  54.  
  55. #define S0 r4
  56. #define S0L r4l
  57. #define S0H r4h
  58.  
  59. #define S1 r5
  60. #define S1L r5l
  61. #define S1H r5h
  62.  
  63. #define S2 r6
  64. #define S2L r6l
  65. #define S2H r6h
  66.  
  67. #ifdef __H8300__
  68. #define MOVP    mov.w    /* pointers are 16 bits */
  69. #define ADDP    add.w
  70. #define CMPP    cmp.w
  71. #define PUSHP    push
  72. #define POPP    pop
  73.  
  74. #define A0P    r0
  75. #define A1P    r1
  76. #define A2P    r2
  77. #define A3P    r3
  78. #define S0P    r4
  79. #define S1P    r5
  80. #define S2P    r6
  81. #endif
  82.  
  83. #ifdef __H8300H__
  84. #define MOVP    mov.l    /* pointers are 32 bits */
  85. #define ADDP    add.l
  86. #define CMPP    cmp.l
  87. #define PUSHP    push.l
  88. #define POPP    pop.l
  89.  
  90. #define A0P    er0
  91. #define A1P    er1
  92. #define A2P    er2
  93. #define A3P    er3
  94. #define S0P    er4
  95. #define S1P    er5
  96. #define S2P    er6
  97.  
  98. #define A0E    e0
  99. #define A1E    e1
  100. #define A2E    e2
  101. #define A3E    e3
  102. #endif
  103.  
  104. #ifdef L_cmpsi2
  105. #ifdef __H8300__
  106.     .section .text
  107.     .align 2
  108.     .global ___cmpsi2
  109. ___cmpsi2:
  110.     cmp.w    A2,A0
  111.     bne    .L2
  112.     cmp.w    A3,A1
  113.     bne    .L2
  114.     mov.w    #1,A0
  115.     rts
  116. .L2:
  117.     cmp.w    A0,A2
  118.     bgt    .L4
  119.     bne    .L3
  120.     cmp.w    A1,A3
  121.     bls    .L3
  122. .L4:
  123.     sub.w    A0,A0
  124.     rts
  125. .L3:
  126.     mov.w    #2,A0
  127. .L5:
  128.     rts
  129.     .end
  130. #endif
  131. #endif /* L_cmpsi2 */
  132.  
  133. #ifdef L_ucmpsi2
  134. #ifdef __H8300__
  135.     .section .text
  136.     .align 2
  137.     .global ___ucmpsi2
  138. ___ucmpsi2:
  139.     cmp.w    A2,A0
  140.     bne    .L2
  141.     cmp.w    A3,A1
  142.     bne    .L2
  143.     mov.w    #1,A0
  144.     rts
  145. .L2:
  146.     cmp.w    A0,A2
  147.     bhi    .L4
  148.     bne    .L3
  149.     cmp.w    A1,A3
  150.     bls    .L3
  151. .L4:
  152.     sub.w    A0,A0
  153.     rts
  154. .L3:
  155.     mov.w    #2,A0
  156. .L5:
  157.     rts
  158.     .end
  159. #endif
  160. #endif /* L_ucmpsi2 */
  161.  
  162. #ifdef L_divhi3
  163.  
  164. ;; HImode divides for the H8/300.
  165. ;; We bunch all of this into one object file since there are several
  166. ;; "supporting routines".
  167.  
  168. ; general purpose normalize routine
  169. ; divisor in A0
  170. ; dividend in A1
  171. ; turns both into +ve numbers, and leaves what the answer sign
  172. ; should be in A2L
  173.  
  174. #ifdef __H8300__
  175.     .section .text
  176.     .align 2
  177. divnorm:
  178.     mov.b    #0x0,A2L
  179.     or    A0H,A0H        ; is divisor > 0
  180.     bge    _lab1            
  181.     not    A0H        ; no - then make it +ve
  182.     not    A0L
  183.     adds    #1,A0            
  184.     xor    #0x1,A2L    ; and remember that in A2L
  185. _lab1:    or    A1H,A1H    ; look at dividend
  186.     bge    _lab2        
  187.     not    A1H        ; it is -ve, make it positive
  188.     not    A1L
  189.     adds    #1,A1
  190.     xor    #0x1,A2L; and toggle sign of result
  191. _lab2:    rts
  192.  
  193. ; A0=A0/A1 signed
  194.  
  195.     .global    ___divhi3
  196. ___divhi3:
  197.     bsr    divnorm
  198.     bsr    ___udivhi3
  199. negans:    or    A2L,A2L    ; should answer be negative ?
  200.     beq    _lab4
  201.     not    A0H    ; yes, so make it so
  202.     not    A0L
  203.     adds    #1,A0
  204. _lab4:    rts    
  205.  
  206. ; A0=A0%A1 signed
  207.  
  208.     .global    ___modhi3
  209. ___modhi3:
  210.     bsr    divnorm
  211.     bsr    ___udivhi3
  212.     mov    A3,A0
  213.     bra    negans
  214.  
  215. ; A0=A0%A1 unsigned
  216.  
  217.     .global    ___umodhi3
  218. ___umodhi3:
  219.     bsr    ___udivhi3
  220.     mov    A3,A0
  221.     rts
  222.  
  223. ; A0=A0/A1 unsigned
  224. ; A3=A0%A1 unsigned
  225. ; A2H trashed
  226. ; D high 8 bits of denom
  227. ; d low 8 bits of denom
  228. ; N high 8 bits of num
  229. ; n low 8 bits of num
  230. ; M high 8 bits of mod
  231. ; m low 8 bits of mod
  232. ; Q high 8 bits of quot
  233. ; q low 8 bits of quot
  234. ; P preserve
  235.  
  236. ; The h8 only has a 16/8 bit divide, so we look at the incoming and
  237. ; see how to partition up the expression.
  238.  
  239.     .global    ___udivhi3
  240. ___udivhi3:
  241.                 ; A0 A1 A2 A3 
  242.                 ; Nn Dd       P
  243.     sub.w    A3,A3        ; Nn Dd xP 00 
  244.     or    A1H,A1H         
  245.     bne    divlongway
  246.     or    A0H,A0H        
  247.     beq    _lab6        
  248.  
  249. ; we know that D == 0 and N is != 0
  250.     mov.b    A0H,A3L        ; Nn Dd xP 0N
  251.     divxu    A1L,A3        ;          MQ
  252.     mov.b    A3L,A0H         ; Q
  253. ; dealt with N, do n
  254. _lab6:    mov.b    A0L,A3L        ;           n
  255.     divxu    A1L,A3        ;          mq
  256.     mov.b    A3L,A0L        ; Qq
  257.     mov.b    A3H,A3L         ;           m
  258.     mov.b    #0x0,A3H    ; Qq       0m
  259.     rts    
  260.  
  261. ; D != 0 - which means the denominator is
  262. ;          loop around to get the result.
  263.  
  264. divlongway:
  265.     mov.b    A0H,A3L        ; Nn Dd xP 0N
  266.     mov.b    #0x0,A0H    ; high byte of answer has to be zero
  267.     mov.b    #0x8,A2H    ;       8
  268. div8:    add.b    A0L,A0L        ; n*=2
  269.     rotxl    A3L        ; Make remainder bigger
  270.     rotxl    A3H        
  271.     sub.w    A1,A3        ; Q-=N
  272.     bhs    setbit        ; set a bit ?
  273.     add.w    A1,A3        ;  no : too far , Q+=N
  274.  
  275.     dec    A2H        
  276.     bne    div8        ; next bit    
  277.     rts    
  278.  
  279. setbit:    inc    A0L        ; do insert bit
  280.     dec    A2H        
  281.     bne    div8        ; next bit    
  282.     rts    
  283.  
  284. #endif /* __H8300__ */
  285. #endif /* L_divhi3 */
  286.  
  287. #ifdef L_divsi3
  288.  
  289. ;; 4 byte integer divides for the H8/300.
  290. ;;
  291. ;; We have one routine which does all the work and lots of 
  292. ;; little ones which prepare the args and massage the sign.
  293. ;; We bunch all of this into one object file since there are several
  294. ;; "supporting routines".
  295.  
  296. #ifdef __H8300H__
  297.     .h8300h
  298. #endif
  299.  
  300.     .section .text
  301.     .align 2
  302.  
  303. ; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest.
  304. ; This function is here to keep branch displacements small.
  305.  
  306. #ifdef __H8300__
  307.  
  308. divnorm:
  309.     mov.b    #0,S2L        ; keep the sign in S2
  310.     mov.b    A0H,A0H        ; is the numerator -ve
  311.     bge    postive
  312.  
  313.     ; negate arg
  314.     not    A0H
  315.     not    A1H
  316.     not    A0L
  317.     not    A1L
  318.  
  319.     add    #1,A1L
  320.     addx    #0,A1H
  321.     addx    #0,A0H
  322.     addx    #0,A0L
  323.  
  324.     mov.b    #1,S2L        ; the sign will be -ve
  325. postive:
  326.     mov.b    A2H,A2H        ; is the denominator -ve
  327.     bge    postive2
  328.     not    A2L        
  329.     not    A2H
  330.     not    A3L
  331.     not    A3H
  332.     add.b    #1,A3L    
  333.     addx    #0,A3H
  334.     addx    #0,A2L
  335.     addx    #0,A2H
  336.     xor    #1,S2L        ; toggle result sign
  337. postive2:
  338.     rts
  339.  
  340. #else /* __H8300H__ */
  341.  
  342. divnorm:
  343.     mov.b    #0,S2L        ; keep the sign in S2
  344.     mov.l    A0P,A0P        ; is the numerator -ve
  345.     bge    postive
  346.  
  347.     neg.l    A0P        ; negate arg
  348.     mov.b    #1,S2L        ; the sign will be -ve
  349.  
  350. postive:
  351.     mov.l    A1P,A1P        ; is the denominator -ve
  352.     bge    postive2
  353.  
  354.     neg.l    A1P        ; negate arg
  355.     xor.b    #1,S2L        ; toggle result sign
  356.  
  357. postive2:
  358.     rts
  359.  
  360. #endif
  361.  
  362. ; numerator in A0/A1
  363. ; denominator in A2/A3
  364.     .global    ___modsi3
  365. ___modsi3:
  366.     PUSHP    S2P        
  367.     PUSHP    S0P
  368.     PUSHP    S1P
  369.  
  370.     bsr    divnorm
  371.     bsr    divmodsi4
  372. #ifdef __H8300__
  373.     mov    S0,A0
  374.     mov    S1,A1
  375. #else
  376.     mov.l    S0P,A0P
  377. #endif
  378.     bra    exitdiv
  379.  
  380.     .global    ___udivsi3
  381. ___udivsi3:
  382.     PUSHP    S2P
  383.     PUSHP    S0P
  384.     PUSHP    S1P
  385.     mov.b    #0,S2L    ; keep sign low
  386.     bsr    divmodsi4
  387.     bra    exitdiv
  388.  
  389.     .global    ___umodsi3
  390. ___umodsi3:
  391.     PUSHP    S2P
  392.     PUSHP    S0P
  393.     PUSHP    S1P
  394.     mov.b    #0,S2L    ; keep sign low
  395.     bsr    divmodsi4
  396. #ifdef __H8300__
  397.     mov    S0,A0
  398.     mov    S1,A1
  399. #else
  400.     mov.l    S0P,A0P
  401. #endif
  402.     bra    exitdiv
  403.     
  404.     .global    ___divsi3
  405. ___divsi3:
  406.     PUSHP    S2P
  407.     PUSHP    S0P
  408.     PUSHP    S1P
  409.     jsr    divnorm
  410.     jsr    divmodsi4
  411.  
  412.     ; examine what the sign should be
  413. exitdiv:
  414.     POPP    S1P
  415.     POPP    S0P
  416.  
  417.     or    S2L,S2L
  418.     beq    reti
  419.     
  420.     ; should be -ve
  421. #ifdef __H8300__
  422.     not    A0H
  423.     not    A1H
  424.     not    A0L
  425.     not    A1L
  426.  
  427.     add    #1,A1L
  428.     addx    #0,A1H
  429.     addx    #0,A0H
  430.     addx    #0,A0L
  431. #else /* __H8300H__ */
  432.     neg.l    A0P
  433. #endif
  434.  
  435. reti:
  436.     POPP    S2P
  437.     rts    
  438.  
  439.     ; takes A0/A1 numerator (A0P for 300h)
  440.     ; A2/A3 denominator (A1P for 300h)
  441.     ; returns A0/A1 quotient (A0P for 300h)
  442.     ; S0/S1 remainder (S0P for 300h)
  443.     ; trashes S2
  444.  
  445. #ifdef __H8300__
  446.  
  447. divmodsi4:
  448.         sub.w    S0,S0        ; zero play area
  449.         mov.w    S0,S1
  450.         mov.b    A2H,S2H
  451.         or    A2L,S2H
  452.         or    A3H,S2H
  453.         bne    DenHighZero
  454.         mov.b    A0H,A0H
  455.         bne    NumByte0Zero
  456.         mov.b    A0L,A0L
  457.         bne    NumByte1Zero
  458.         mov.b    A1H,A1H
  459.         bne    NumByte2Zero
  460.         bra    NumByte3Zero
  461. NumByte0Zero:
  462.     mov.b    A0H,S1L
  463.         divxu    A3L,S1
  464.         mov.b    S1L,A0H
  465. NumByte1Zero:
  466.     mov.b    A0L,S1L
  467.         divxu    A3L,S1
  468.         mov.b    S1L,A0L
  469. NumByte2Zero:
  470.     mov.b    A1H,S1L
  471.         divxu    A3L,S1
  472.         mov.b    S1L,A1H
  473. NumByte3Zero:
  474.     mov.b    A1L,S1L
  475.         divxu    A3L,S1
  476.         mov.b    S1L,A1L
  477.  
  478.         mov.b    S1H,S1L
  479.         mov.b    #0x0,S1H
  480.         rts    
  481.  
  482. ; have to do the divide by shift and test
  483. DenHighZero:
  484.     mov.b    A0H,S1L
  485.         mov.b    A0L,A0H
  486.         mov.b    A1H,A0L
  487.         mov.b    A1L,A1H
  488.  
  489.         mov.b    #0,A1L
  490.         mov.b    #24,S2H    ; only do 24 iterations
  491.  
  492. nextbit:
  493.     add.w    A1,A1    ; double the answer guess
  494.         rotxl    A0L
  495.         rotxl    A0H
  496.  
  497.         rotxl    S1L    ; double remainder
  498.         rotxl    S1H
  499.         rotxl    S0L
  500.         rotxl    S0H
  501.         sub.w    A3,S1    ; does it all fit
  502.         subx    A2L,S0L
  503.         subx    A2H,S0H
  504.         bhs    setone     
  505.  
  506.         add.w    A3,S1    ; no, restore mistake
  507.         addx    A2L,S0L
  508.         addx    A2H,S0H
  509.  
  510.         dec    S2H
  511.         bne    nextbit
  512.         rts    
  513.     
  514. setone:
  515.     inc    A1L
  516.         dec    S2H
  517.         bne    nextbit
  518.         rts    
  519.  
  520. #else /* __H8300H__ */
  521.  
  522. divmodsi4:
  523.     sub.l    S0P,S0P        ; zero play area
  524.     mov.w    A1E,A1E        ; denominator top word 0?
  525.     bne    DenHighZero
  526.  
  527.     ; do it the easy way, see page 107 in manual
  528.     mov.w    A0E,A2
  529.     extu.l    A2P
  530.     divxu.w    A1,A2P
  531.     mov.w    A2E,A0E
  532.     divxu.w    A1,A0P
  533.     mov.w    A0E,S0
  534.     mov.w    A2,A0E
  535.     extu.l    S0P
  536.     rts
  537.  
  538. DenHighZero:
  539.     mov.w    A0E,A2
  540.     mov.b    A2H,S0L
  541.     mov.b    A2L,A2H
  542.     mov.b    A0H,A2L
  543.     mov.w    A2,A0E
  544.     mov.b    A0L,A0H
  545.     mov.b    #0,A0L
  546.     mov.b    #24,S2H        ; only do 24 iterations
  547.  
  548. nextbit:
  549.     shll.l    A0P        ; double the answer guess
  550.     rotxl.l    S0P        ; double remainder
  551.     sub.l    A1P,S0P        ; does it all fit?
  552.     bhs    setone
  553.  
  554.     add.l    A1P,S0P        ; no, restore mistake
  555.     dec    S2H
  556.     bne    nextbit
  557.     rts
  558.  
  559. setone:
  560.     inc    A0L
  561.     dec    S2H
  562.     bne    nextbit
  563.     rts
  564.  
  565. #endif
  566. #endif /* L_divsi3 */
  567.  
  568. #ifdef L_mulhi3
  569.  
  570. ;; HImode multiply.
  571. ; The h8 only has an 8*8->16 multiply.
  572. ; The answer is the same as:
  573. ; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256
  574. ; (we can ignore A1.h * A0.h cause that will all off the top)
  575. ; A0 in
  576. ; A1 in 
  577. ; A0 answer
  578.  
  579. #ifdef __H8300__
  580.     .section .text
  581.     .align 2
  582.     .global    ___mulhi3
  583. ___mulhi3:
  584.     mov.b    A1L,A2L        ; A2l gets srcb.l
  585.     mulxu    A0L,A2        ; A2 gets first sub product 
  586.  
  587.     mov.b    A0H,A3L        ; prepare for
  588.     mulxu    A1L,A3        ; second sub product
  589.  
  590.     add.b    A3L,A2H        ; sum first two terms
  591.  
  592.     mov.b    A1H,A3L        ; third sub product
  593.     mulxu    A0L,A3        
  594.  
  595.     add.b    A3L,A2H        ; almost there
  596.     mov.w    A2,A0        ; that is
  597.     rts
  598.  
  599. #endif
  600. #endif /* L_mulhi3 */
  601.  
  602. #ifdef L_mulsi3
  603.  
  604. ;; SImode multiply.
  605. ;; 
  606. ;; I think that shift and add may be sufficient for this.  Using the
  607. ;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead.  This way
  608. ;; the inner loop uses maybe 20 cycles + overhead, but terminates
  609. ;; quickly on small args.
  610. ;;
  611. ;; A0/A1 src_a
  612. ;; A2/A3 src_b
  613. ;;
  614. ;;  while (a) 
  615. ;;    {
  616. ;;      if (a & 1)
  617. ;;        r += b;
  618. ;;      a >>= 1;
  619. ;;      b <<= 1;
  620. ;;    }
  621.  
  622.     .section .text
  623.     .align 2
  624.  
  625. #ifdef __H8300__
  626.  
  627.     .global    ___mulsi3
  628. ___mulsi3:
  629.     PUSHP    S0P
  630.     PUSHP    S1P
  631.     PUSHP    S2P
  632.     
  633.     sub.w    S0,S0
  634.     sub.w    S1,S1
  635.     
  636.     ; while (a)
  637. _top:    mov.w    A0,A0
  638.     bne    _more
  639.     mov.w    A1,A1
  640.     beq    _done
  641. _more:    ; if (a & 1)
  642.     bld    #0,A1L
  643.     bcc    _nobit
  644.     ; r += b
  645.     add.w    A3,S1
  646.     addx    A2L,S0L
  647.     addx    A2H,S0H
  648. _nobit:
  649.     ; a >>= 1
  650.     shlr    A0H
  651.     rotxr    A0L
  652.     rotxr    A1H
  653.     rotxr    A1L
  654.     
  655.     ; b <<= 1
  656.     add.w    A3,A3
  657.     addx    A2L,A2L
  658.     addx    A2H,A2H
  659.     bra     _top
  660.  
  661. _done:
  662.     mov.w    S0,A0    
  663.     mov.w    S1,A1
  664.     POPP    S2P
  665.     POPP    S1P
  666.     POPP    S0P
  667.     rts
  668.  
  669. #else /* __H8300H__ */
  670.  
  671.     .h8300h
  672.  
  673.     .global    ___mulsi3
  674. ___mulsi3:
  675.     sub.l    A2P,A2P
  676.  
  677.     ; while (a)
  678. _top:    mov.l    A0P,A0P
  679.     beq    _done
  680.  
  681.     ; if (a & 1)
  682.     bld    #0,A0L
  683.     bcc    _nobit
  684.  
  685.     ; r += b
  686.     add.l    A1P,A2P
  687.  
  688. _nobit:
  689.     ; a >>= 1
  690.     shlr.l    A0P
  691.  
  692.     ; b <<= 1
  693.     shll.l    A1P
  694.     bra    _top
  695.  
  696. _done:
  697.     mov.l    A2P,A0P
  698.     rts
  699.  
  700. #endif
  701. #endif /* L_mulsi3 */
  702.